﻿#include <iostream>
#include <algorithm>
#include <thread>
#include <string>
#include <exception>
#include <vector>
//#include<cstdlib>
#define __STDC_FORMAT_MACROS
extern "C" {
#include "libavutil/mathematics.h"
#include "libavformat/avformat.h"
};
#include "../Utils/NvCodecUtils.h"
#include"unreDec_api.h"

#ifndef SPLITCPUONLY
#include <cuda.h>
#include "NvDecoder/NvDecoder.h"
#include "../Utils/FFmpegDemuxer.h"
#include "../Common/AppDecUtils.h"
#endif
using namespace std;
#ifndef SPLITCPUONLY
extern CUcontext cuContextGlobal;
#endif


bool writeVideoHeader(AVFormatContext* ifmtCtx, AVFormatContext* ofmtCtx, string out_filename) 
{
    AVOutputFormat* ofmt = NULL;
    int ret;
    ofmt = ofmtCtx->oformat;
    for (int i = 0; i < ifmtCtx->nb_streams; i++) {
        AVStream* in_stream = ifmtCtx->streams[i];

        AVStream* out_stream = avformat_new_stream(ofmtCtx, in_stream->codec->codec);
        if (!out_stream) {
            return false;
        }
        ret = avcodec_copy_context(out_stream->codec, in_stream->codec);
        if (ret < 0) {
            return false;
        }
        out_stream->codec->
                codec_tag = 0;
        if (ofmtCtx->oformat->flags & AVFMT_GLOBALHEADER)
            out_stream->codec->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
    }
    if (!(ofmt->flags & AVFMT_NOFILE))
    {
        ret = avio_open(&ofmtCtx->pb, out_filename.c_str(), AVIO_FLAG_WRITE);
        if (ret < 0) {
            return false;
        }
    }
    ret = avformat_write_header(ofmtCtx, NULL);
    if (ret < 0)
    {
        return false;
    }
    return true;
}

int splitMp4B(char* fileIn, char* outPathTemplate, vector<uint64_t> &vecKeyFramePos)
{
    int ret;
    AVFormatContext* ifmtCtx=NULL;
    AVFormatContext* ofmtCtx;
    if ((ret = avformat_open_input(&ifmtCtx, fileIn, 0, 0)) < 0) {
        return -1;
    }
    if ((ret = avformat_find_stream_info(ifmtCtx, 0)) < 0) {
        return -1;
    }
    int number = 0;

    char temp_name[256];
    sprintf(temp_name, outPathTemplate, number);

    avformat_alloc_output_context2(&ofmtCtx, NULL, NULL, temp_name);
    if (!ofmtCtx)
    {
        std::cout << "Alloc out AVFormatContext failing.\n" << std::endl; return -7;
    }
    if (!writeVideoHeader(ifmtCtx, ofmtCtx, temp_name)) return -8;

    AVPacket readPkt, splitKeyPacket;
    av_init_packet(&splitKeyPacket);
    splitKeyPacket.data = NULL;
    splitKeyPacket.size = 0;

    vector<uint64_t>::iterator keyFrameIter = vecKeyFramePos.begin();

    uint64_t keyFrame_index = *keyFrameIter;
    ++keyFrameIter;
    uint64_t frame_index = 0;
    int64_t lastPts = 0;
    int64_t lastDts = 0;
    int64_t prePts = 0;
    int64_t preDts = 0;
    while (1) {
        ++frame_index;
        ret = av_read_frame(ifmtCtx, &readPkt);
        if (ret < 0) {
            break;
        }
        av_packet_rescale_ts(&readPkt, ifmtCtx->streams[readPkt.stream_index]->time_base,
                ofmtCtx->streams[readPkt.stream_index]->time_base);
        prePts = readPkt.pts;
        preDts = readPkt.dts;
        readPkt.pts -= lastPts;
        readPkt.dts -= lastDts;
        if (readPkt.pts < readPkt.dts) {
            readPkt.pts = readPkt.dts + 1;
        }
        if (readPkt.flags & AV_PKT_FLAG_KEY && frame_index == keyFrame_index) {
            av_copy_packet(&splitKeyPacket, &readPkt);
        }
        else {
            ret = av_interleaved_write_frame(ofmtCtx, &readPkt);
            if (ret < 0) {
                break;
            }
        }

        if (frame_index == keyFrame_index) {
            lastDts = preDts;
            lastPts = prePts;
            if (keyFrameIter != vecKeyFramePos.end()) {
                keyFrame_index = *keyFrameIter;
                ++keyFrameIter;
            }
            av_write_trailer(ofmtCtx);
            avio_close(ofmtCtx->pb);
            avformat_free_context(ofmtCtx);
            ++number;

    sprintf(temp_name, outPathTemplate, number);
            //            pStruct->retOutCnt++;
            avformat_alloc_output_context2(&ofmtCtx, NULL, NULL, temp_name);
            if (!ofmtCtx) {
                return false;
            }
            if (!writeVideoHeader(ifmtCtx, ofmtCtx, temp_name)) {
                return false;
            }
            splitKeyPacket.pts = 0;
            splitKeyPacket.dts = 0;
            ret = av_interleaved_write_frame(ofmtCtx, &splitKeyPacket);
        }
        av_packet_unref(&readPkt);
    }
    av_packet_unref(&splitKeyPacket);

    av_write_trailer(ofmtCtx);
    avio_close(ofmtCtx->pb);
    avformat_free_context(ofmtCtx);

    avformat_close_input(&ifmtCtx);

    return 1;
}

int splitMp4C(char* fileIn, char* outPathTemplate, int nSeg)
{
    try
    {
        CheckInputFile(fileIn);
    }
    catch (...)
    {
        return -1;
    }

    int video_index;
    av_register_all();
    avformat_network_init();
    AVFormatContext* ifmtCtx = avformat_alloc_context();

    AVPacket readPkt, splitKeyPacket;
    int ret;
    if (avformat_open_input(&ifmtCtx, fileIn, 0, 0) < 0)
    {
        std::cout<< "Could not open file.\n" <<std::endl; return -5;
    }
    if (avformat_find_stream_info(ifmtCtx, 0) < 0)
    {
        std::cout << "Fail to find stream information\n" << std::endl; return -6;
    }
    for (int i = 0; i < ifmtCtx->nb_streams; i++)
    {
        AVStream* in_stream = ifmtCtx->streams[i];
        if (in_stream->codec->codec_type == AVMEDIA_TYPE_VIDEO)video_index = i;
    }

	std::cout<<"video_index="<<video_index<<"\n";

    vector<uint64_t> vecKeyFramePos;
    uint64_t frame_index = 0;
    while (1) {
        ++frame_index;
        ret = av_read_frame(ifmtCtx, &readPkt);
        if (ret < 0) {
            break;
        }
        if (readPkt.stream_index == video_index) {
            if (readPkt.flags & AV_PKT_FLAG_KEY) {
               // std::cout << frame_index << std::endl;
                vecKeyFramePos.push_back(frame_index);
            }
        }
        av_packet_unref(&readPkt);
    }

    avformat_close_input(&ifmtCtx);

    if(vecKeyFramePos.size()>=nSeg)
    {
        uint64_t step=frame_index/nSeg;
        std::vector<uint64_t> vecKeyFramePosNew(nSeg-1);
        size_t i;
        size_t j=0;
        for(i=1;i<nSeg;i++)
            while(j<vecKeyFramePos.size())
            {
                if(vecKeyFramePos[j]>i*step)
                {
                    vecKeyFramePosNew[i-1]=vecKeyFramePos[j];
                    break;
                }
                j++;
            }
        vecKeyFramePos.assign(vecKeyFramePosNew.begin(), vecKeyFramePosNew.end());
    }

   std::cout<<"vecKeyFramePos="<<vecKeyFramePos.size()<<"\n";
   for(auto d : vecKeyFramePos) std::cout<<d<<"\t";
   std::cout<<"\n";

    ret=splitMp4B(fileIn, outPathTemplate, vecKeyFramePos);
    return (ret>0)?(vecKeyFramePos.size()+1):ret;
}


#ifndef SPLITCPUONLY
class CentextSet
{
private:
    CentextSet() {};
    CentextSet(const CentextSet& other) {};
public:
    static CentextSet* GetInstance()
    {
        static CentextSet instance;
        return &instance;
    }
    static CentextSet* instance_;
    static std::vector<CUcontext>cuContextGlobals;

};

int splitMp4(char* fileIn, char* outPath, decoderParam* pStruct)
{
    //if (cuContextGlobal==NULL)
    if (CentextSet::GetInstance()->cuContextGlobals[0]==NULL)
    {
        return -11;
    }
    try
    {
        CheckInputFile(fileIn);
    }
    catch (...)
    {
        return -1;
    }
    int cropRight = pStruct->cropRight;
    int cropLeft = pStruct->cropLeft;
    int cropBottom = pStruct->cropBottom;
    int cropTop = pStruct->cropTop;
    int resizeH = pStruct->resizeH;
    int resizeW = pStruct->resizeW;
    Rect cropRect = {};
    Dim resizeDim = {};
    if (cropRight <= 0 && cropLeft <= 0 && cropBottom <= 0 && cropTop <= 0) {}
    else
    {
        if ((cropRight - cropLeft) % 2 == 1 || (cropBottom - cropTop) % 2 == 1) return -2;
        cropRect.b = cropBottom;
        cropRect.t = cropTop;
        cropRect.l = cropLeft;
        cropRect.r = cropRight;
    }
    if (resizeH <= 0 && resizeW <= 0) {}
    else
    {
        if (resizeH % 2 == 1 || resizeW % 2 == 1) return -3;
        resizeDim.h = resizeH;
        resizeDim.w = resizeW;
    }
    try
    {
        FFmpegDemuxer demuxer(fileIn);
        NvDecoder dec(CentextSet::GetInstance()->cuContextGlobals[0], false, FFmpeg2NvCodecId(demuxer.GetVideoCodec()), false, false, &cropRect, &resizeDim);
        int nVideoBytes = 0, nFrameReturned = 0, nFrame = 0;
        uint8_t* pVideo = NULL, * pFrame;
        bool bDecodeOutSemiPlanar = false;
        do {
            demuxer.Demux(&pVideo, &nVideoBytes);
            nFrameReturned = dec.Decode(pVideo, nVideoBytes);
            if (!nFrame && nFrameReturned)
            {
                pStruct->retDecodeWidth = dec.GetWidth();
                pStruct->retDecodeHeigth = dec.GetHeight();
                pStruct->retFrameSize = dec.GetFrameSize();
                break;
            }
        } while (nVideoBytes);
    }
    catch (...)
    {
        return -4;
    }

    int frameHeight = pStruct->retDecodeHeigth;
    int frameWidth = pStruct->retDecodeWidth;
    unsigned long long frameSize = static_cast<unsigned long long>(pStruct->retFrameSize);
    if (pStruct->rawDataType != 0)
    {
        frameSize * 2;
    }
    unsigned long long  memLmt = 1024ull * 1024ull * static_cast<unsigned long long>(pStruct->lmtMB);
    int frameCntInEachSegment = memLmt / frameSize - 1;
    if (frameCntInEachSegment<1)
    {
        std::cout << "memLmt so small!\n" << std::endl;            return -12;
    }
    int splitVideoSize = frameCntInEachSegment;
    int video_index;
    av_register_all();
    avformat_network_init();
    AVFormatContext* ifmtCtx = avformat_alloc_context();
    AVFormatContext* ofmtCtx;
    string inputFileName = fileIn;
    string outputFileName = outPath;
    string suffixName = ".mp4";
    AVPacket readPkt, splitKeyPacket;
    int ret;
    if (avformat_open_input(&ifmtCtx, inputFileName.c_str(), 0, 0) < 0)
    {
        std::cout<< "Could not open file.\n" <<std::endl; return -5;
    }
    if (avformat_find_stream_info(ifmtCtx, 0) < 0)
    {
        std::cout << "Fail to find stream information\n" << std::endl; return -6;
    }
    for (int i = 0; i < ifmtCtx->nb_streams; i++)
    {
        AVStream* in_stream = ifmtCtx->streams[i];
        if (in_stream->codec->codec_type == AVMEDIA_TYPE_VIDEO)video_index = i;
    }
    int den = ifmtCtx->streams[video_index]->r_frame_rate.den;//1
    int num = ifmtCtx->streams[video_index]->r_frame_rate.num;//25
    int fps = num / den;
    pStruct->retFps = fps;
    string save_name;
    save_name = outputFileName;
    string temp_name = outputFileName + "0" + suffixName;
    pStruct->retOutCnt = 1;
    avformat_alloc_output_context2(&ofmtCtx, NULL, NULL, temp_name.c_str());
    if (!ofmtCtx)
    {
        std::cout << "Alloc out AVFormatContext failing.\n" << std::endl; return -7;
    }
    if (!writeVideoHeader(ifmtCtx, ofmtCtx, temp_name)) return -8;
    vector<uint64_t> vecKeyFramePos;
    vector<std::pair<uint64_t, int>>  formerPos;
    uint64_t frame_index = 0;
    uint64_t keyFrame_index = 0;
    uint64_t first_keyFrame_index = 0;
    int frameCount = 0;
    int firstFrameCount = 0;
    while (1) {
        ++frame_index;
        ret = av_read_frame(ifmtCtx, &readPkt);
        if (ret < 0) {
            break;
        }
        if (readPkt.stream_index == video_index) {

            //std::cout << frame_index << "  " << frameCount << std::endl;
            ++frameCount;
            if (readPkt.flags & AV_PKT_FLAG_KEY) {
                keyFrame_index = frame_index;
                if (first_keyFrame_index == 0)
                {
                    first_keyFrame_index = keyFrame_index;
                    firstFrameCount = frameCount;
                }
            }
#if 1
            if (formerPos.size() == 0)
            {
                if (first_keyFrame_index != keyFrame_index)
                {
                    formerPos.emplace_back(std::make_pair(keyFrame_index, frameCount));
                }
            }
            else if (formerPos[formerPos.size() - 1].first != keyFrame_index)
            {
                formerPos.emplace_back(std::make_pair(keyFrame_index, frameCount));
            }
            if (frameCount > splitVideoSize)
            {
                if (vecKeyFramePos.size() == 0)
                {
                    if (first_keyFrame_index != keyFrame_index)
                    {
                        vecKeyFramePos.push_back(keyFrame_index);
                        frameCount -= formerPos[formerPos.size() - 1].second;
                        vecKeyFramePos[vecKeyFramePos.size() - 1] = formerPos[formerPos.size() - 1].first;
                    }
                }
                else if (vecKeyFramePos[vecKeyFramePos.size() - 1] != keyFrame_index)
                {
                    vecKeyFramePos.push_back(keyFrame_index);
                    frameCount -= formerPos[formerPos.size() - 1].second;
                    vecKeyFramePos[vecKeyFramePos.size() - 1] = formerPos[formerPos.size() - 1].first;
                }
            }
#else
            if (frameCount > splitVideoSize) {
                if (vecKeyFramePos.size() == 0)
                {
                    if (first_keyFrame_index != keyFrame_index)
                    {
                        vecKeyFramePos.push_back(keyFrame_index);
                        frameCount = 0;
                    }
                }
                else if (vecKeyFramePos[vecKeyFramePos.size() - 1] != keyFrame_index)
                {
                    vecKeyFramePos.push_back(keyFrame_index);
                    frameCount = 0;
                }
            }
#endif
        }
        av_packet_unref(&readPkt);
    }
    if (formerPos.size() > 0)
    {
        formerPos[0].second -= firstFrameCount;
    }
    formerPos.emplace_back(std::make_pair(0, frameCount + 1));
    avformat_close_input(&ifmtCtx);
    ifmtCtx = NULL;
    if (vecKeyFramePos.size()==0)
    {
        std::cout<<"no need split."<<std::endl;
        return 100;
    }
    if ((ret = avformat_open_input(&ifmtCtx, inputFileName.c_str(), 0, 0)) < 0) {
        return -1;
    }
    if ((ret = avformat_find_stream_info(ifmtCtx, 0)) < 0) {
        return -1;
    }
    int number = 0;
    av_init_packet(&splitKeyPacket);
    splitKeyPacket.data = NULL;
    splitKeyPacket.size = 0;
    if (vecKeyFramePos.empty()) {
        vecKeyFramePos.push_back(frame_index);
    }
    vector<uint64_t> vecKeyFramePosNoReci;
    vecKeyFramePosNoReci.reserve(vecKeyFramePos.size());
    for (auto d : vecKeyFramePos)
    {
        if (vecKeyFramePosNoReci.end() == std::find(vecKeyFramePosNoReci.begin(), vecKeyFramePosNoReci.end(), d))
        {
            vecKeyFramePosNoReci.emplace_back(d);
        }
    }
    std::swap(vecKeyFramePosNoReci, vecKeyFramePos);
    vector<uint64_t>::iterator keyFrameIter = vecKeyFramePos.begin();

    std::cout<<"vecKeyFramePos="<<vecKeyFramePos.size()<<"\n";
    for(auto d : vecKeyFramePos) std::cout<<d<<"\t";
    std::cout<<"\n";

    keyFrame_index = *keyFrameIter;
    ++keyFrameIter;
    frame_index = 0;
    int64_t lastPts = 0;
    int64_t lastDts = 0;
    int64_t prePts = 0;
    int64_t preDts = 0;
    while (1) {
        ++frame_index;
        ret = av_read_frame(ifmtCtx, &readPkt);
        if (ret < 0) {
            break;
        }
        av_packet_rescale_ts(&readPkt, ifmtCtx->streams[readPkt.stream_index]->time_base,
                ofmtCtx->streams[readPkt.stream_index]->time_base);
        prePts = readPkt.pts;
        preDts = readPkt.dts;
        readPkt.pts -= lastPts;
        readPkt.dts -= lastDts;
        if (readPkt.pts < readPkt.dts) {
            readPkt.pts = readPkt.dts + 1;
        }
        if (readPkt.flags & AV_PKT_FLAG_KEY && frame_index == keyFrame_index) {
            av_copy_packet(&splitKeyPacket, &readPkt);
        }
        else {
            ret = av_interleaved_write_frame(ofmtCtx, &readPkt);
            if (ret < 0) {
                break;
            }
        }

        if (frame_index == keyFrame_index) {
            lastDts = preDts;
            lastPts = prePts;
            if (keyFrameIter != vecKeyFramePos.end()) {
                keyFrame_index = *keyFrameIter;
                ++keyFrameIter;
            }
            av_write_trailer(ofmtCtx);
            avio_close(ofmtCtx->pb);
            avformat_free_context(ofmtCtx);
            ++number;
            char num[10];
            sprintf(num, "%d", number);
            temp_name = save_name + num + suffixName;
            pStruct->retOutCnt++;
            avformat_alloc_output_context2(&ofmtCtx, NULL, NULL, temp_name.c_str());
            if (!ofmtCtx) {
                return false;
            }
            if (!writeVideoHeader(ifmtCtx, ofmtCtx, temp_name)) {
                return false;
            }
            splitKeyPacket.pts = 0;
            splitKeyPacket.dts = 0;
            ret = av_interleaved_write_frame(ofmtCtx, &splitKeyPacket);
        }
        av_packet_unref(&readPkt);
    }
    av_packet_unref(&splitKeyPacket);
    av_write_trailer(ofmtCtx);
    avformat_close_input(&ifmtCtx);
    avio_close(ofmtCtx->pb);
    avformat_free_context(ofmtCtx);


    return true;
}


#endif
#if 0
bool executeSplit(char* inFile, char* outFile, int splitVideoSize) {
    int video_index;
    av_register_all();
    avformat_network_init();
    AVFormatContext* ifmtCtx = avformat_alloc_context();
    AVFormatContext* ofmtCtx;
    string inputFileName = inFile;
    string outputFileName = outFile;
    string suffixName = ".mp4";
    AVPacket readPkt, splitKeyPacket;
    int ret;
    if (avformat_open_input(&ifmtCtx, inputFileName.c_str(), 0, 0) < 0) {
        LOGE("Could not open file.\n")
                return false;
    }

    if (avformat_find_stream_info(ifmtCtx, 0) < 0) {
        LOGE("Fail to find stream information\n")
                return false;
    }

    for (int i = 0; i < ifmtCtx->nb_streams; i++) {

        AVStream* in_stream = ifmtCtx->streams[i];
        if (in_stream->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
            video_index = i;
        }
    }

    int den = ifmtCtx->streams[video_index]->r_frame_rate.den;//1
    int num = ifmtCtx->streams[video_index]->r_frame_rate.num;//25

    int fps = num / den;
    string save_name;
    save_name = outputFileName.substr(0, outputFileName.find_last_of("."));
    string temp_name = save_name + "0" + suffixName;
    avformat_alloc_output_context2(&ofmtCtx, NULL, NULL, temp_name.c_str());
    if (!ofmtCtx) {
        LOGE("Alloc out AVFormatContext failing.\n");
        return false;
    }
    if (!writeVideoHeader(ifmtCtx, ofmtCtx, temp_name)) {
        return false;
    }
    vector<uint64_t> vecKeyFramePos;
    vector<std::pair<uint64_t, int>>  formerPos;
    uint64_t frame_index = 0;
    uint64_t keyFrame_index = 0;
    uint64_t first_keyFrame_index = 0;
    int frameCount = 0;
    int firstFrameCount = 0;
    //读取分割点附近的关键帧位置
    while (1) {
        ++frame_index;
        ret = av_read_frame(ifmtCtx, &readPkt);
        if (ret < 0) {
            break;
        }
        if (readPkt.stream_index == video_index) {

            //std::cout << frame_index << "  " << frameCount << std::endl;
            ++frameCount;
            if (readPkt.flags & AV_PKT_FLAG_KEY) {
                keyFrame_index = frame_index;
                if (first_keyFrame_index == 0)
                {
                    first_keyFrame_index = keyFrame_index;
                    firstFrameCount = frameCount;
                }
                std::cout << " *************************************************** " << frame_index << "  " << frameCount << std::endl;
            }
#if 1
            if (formerPos.size() == 0)
            {
                if (first_keyFrame_index != keyFrame_index)
                {
                    formerPos.emplace_back(std::make_pair(keyFrame_index, frameCount));
                }
            }
            else if (formerPos[formerPos.size() - 1].first != keyFrame_index)
            {
                formerPos.emplace_back(std::make_pair(keyFrame_index, frameCount));
            }
            if (frameCount > splitVideoSize)
            {
                if (vecKeyFramePos.size() == 0)
                {
                    if (first_keyFrame_index != keyFrame_index)
                    {
                        vecKeyFramePos.push_back(keyFrame_index);
                        LOGE("KeyFrame 索引%d", keyFrame_index);
                        frameCount -= formerPos[formerPos.size() - 1].second;
                        vecKeyFramePos[vecKeyFramePos.size() - 1] = formerPos[formerPos.size() - 1].first;
                    }
                }
                else if (vecKeyFramePos[vecKeyFramePos.size() - 1] != keyFrame_index)
                {
                    vecKeyFramePos.push_back(keyFrame_index);
                    LOGE("KeyFrame 索引%d", keyFrame_index);
                    frameCount -= formerPos[formerPos.size() - 1].second;
                    vecKeyFramePos[vecKeyFramePos.size() - 1] = formerPos[formerPos.size() - 1].first;
                }
            }
#else

            if (frameCount > splitVideoSize) {
                if (vecKeyFramePos.size() == 0)
                {
                    if (first_keyFrame_index != keyFrame_index)
                    {
                        vecKeyFramePos.push_back(keyFrame_index);
                        LOGE("KeyFrame 索引%d", keyFrame_index);
                        frameCount = 0;
                    }
                }
                else if (vecKeyFramePos[vecKeyFramePos.size() - 1] != keyFrame_index)
                {
                    vecKeyFramePos.push_back(keyFrame_index);
                    LOGE("KeyFrame 索引%d", keyFrame_index);
                    frameCount = 0;
                }
            }
#endif
        }
        av_packet_unref(&readPkt);
    }
    if (formerPos.size() > 0)
    {
        formerPos[0].second -= firstFrameCount;
    }
    formerPos.emplace_back(std::make_pair(0, frameCount + 1));
    avformat_close_input(&ifmtCtx);
    ifmtCtx = NULL;
    //为了重新获取avformatcontext
    if ((ret = avformat_open_input(&ifmtCtx, inputFileName.c_str(), 0, 0)) < 0) {
        return -1;
    }

    if ((ret = avformat_find_stream_info(ifmtCtx, 0)) < 0) {
        return -1;
    }
    int number = 0;
    av_init_packet(&splitKeyPacket);
    splitKeyPacket.data = NULL;
    splitKeyPacket.size = 0;
    //时长对应的帧数超过视频的总视频帧数，则拷贝完整视频
    if (vecKeyFramePos.empty()) {
        vecKeyFramePos.push_back(frame_index);
    }
    vector<uint64_t> vecKeyFramePosNoReci;
    vecKeyFramePosNoReci.reserve(vecKeyFramePos.size());
    for (auto d : vecKeyFramePos)
    {
        if (vecKeyFramePosNoReci.end() == std::find(vecKeyFramePosNoReci.begin(), vecKeyFramePosNoReci.end(), d))
        {
            vecKeyFramePosNoReci.emplace_back(d);
        }
    }
    std::swap(vecKeyFramePosNoReci, vecKeyFramePos);
    vector<uint64_t>::iterator keyFrameIter = vecKeyFramePos.begin();

    keyFrame_index = *keyFrameIter;
    ++keyFrameIter;
    frame_index = 0;
    int64_t lastPts = 0;
    int64_t lastDts = 0;
    int64_t prePts = 0;
    int64_t preDts = 0;
    while (1) {
        ++frame_index;
        ret = av_read_frame(ifmtCtx, &readPkt);
        if (ret < 0) {
            break;
        }
        LOGE("帧索引%lld", frame_index);
        av_packet_rescale_ts(&readPkt, ifmtCtx->streams[readPkt.stream_index]->time_base,
                ofmtCtx->streams[readPkt.stream_index]->time_base);
        prePts = readPkt.pts;
        preDts = readPkt.dts;
        readPkt.pts -= lastPts;
        LOGE("readPkt.pts %lld lastPts %lld", readPkt.pts, lastPts);
        readPkt.dts -= lastDts;
        LOGE("readPkt.dts %lld lastDts %lld", readPkt.dts, lastDts);

        if (readPkt.pts < readPkt.dts) {
            readPkt.pts = readPkt.dts + 1;
        }
        //为分割点处的关键帧要进行拷贝
        if (readPkt.flags & AV_PKT_FLAG_KEY && frame_index == keyFrame_index) {
            av_copy_packet(&splitKeyPacket, &readPkt);
        }
        else {
            ret = av_interleaved_write_frame(ofmtCtx, &readPkt);
            if (ret < 0) {
                break;
            }
        }

        if (frame_index == keyFrame_index) {
            lastDts = preDts;
            lastPts = prePts;
            if (keyFrameIter != vecKeyFramePos.end()) {
                keyFrame_index = *keyFrameIter;
                ++keyFrameIter;
            }
            av_write_trailer(ofmtCtx);
            avio_close(ofmtCtx->pb);
            avformat_free_context(ofmtCtx);
            ++number;
            char num[10];
            sprintf(num, "%d", number);
            temp_name = save_name + num + suffixName;
            avformat_alloc_output_context2(&ofmtCtx, NULL, NULL, temp_name.c_str());
            if (!ofmtCtx) {
                return false;
            }
            if (!writeVideoHeader(ifmtCtx, ofmtCtx, temp_name)) {
                return false;
            }
            splitKeyPacket.pts = 0;
            splitKeyPacket.dts = 0;
            //把上一个分片处的关键帧写入到下一个分片的起始处，保证下一个分片的开头为I帧
            ret = av_interleaved_write_frame(ofmtCtx, &splitKeyPacket);
        }
        av_packet_unref(&readPkt);
    }
    av_packet_unref(&splitKeyPacket);
    av_write_trailer(ofmtCtx);
    avformat_close_input(&ifmtCtx);
    avio_close(ofmtCtx->pb);
    avformat_free_context(ofmtCtx);
    return true;
}
#endif
